﻿using System.Linq;
using System.Runtime.Loader;

using Autofac;
using Autofac.Extensions.DependencyInjection;

using Jack.EntityFrameworkCore.WebAPITest.IOCTags;

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyModel;
using Microsoft.Extensions.Hosting;

namespace Jack.EntityFrameworkCore.WebAPITest
{
    public static class AutofacExtensions
    {
        public static IHostBuilder UseAutofac(this IHostBuilder host)
        {
            host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
            host.ConfigureContainer<ContainerBuilder>(container =>
            {
                var libs = DependencyContext.Default.CompileLibraries.Where(lib => lib.Serviceable == false && lib.Type == "project").Select(lib => lib.Name).ToList();

                var assemblies = libs.Select(lib => AssemblyLoadContext.Default.LoadFromAssemblyName(new System.Reflection.AssemblyName(lib))).ToArray();

                container
                    .RegisterAssemblyTypes(assemblies)
                    .Where(type => type.IsAbstract == false && type.IsAssignableTo<ISingletonIocTag>())
                    .AsSelf()
                    .AsImplementedInterfaces()
                    .SingleInstance()
                    .PropertiesAutowired();

                container
                    .RegisterAssemblyTypes(assemblies)
                    .Where(type => type.IsAbstract == false && type.IsAssignableTo<IScopedIocTag>())
                    .AsSelf()
                    .AsImplementedInterfaces()
                    .InstancePerLifetimeScope()
                    .PropertiesAutowired();

                container
                    .RegisterAssemblyTypes(assemblies)
                    .Where(type => type.IsAbstract == false && type.IsAssignableTo<ITransientIocTag>())
                    .AsSelf()
                    .AsImplementedInterfaces()
                    .InstancePerDependency()
                    .PropertiesAutowired();

                container
                    .RegisterAssemblyTypes(assemblies)
                    .Where(type => type.IsAbstract == false && type.IsAssignableTo<ControllerBase>())
                    .AsSelf()
                    .InstancePerDependency()
                    .PropertiesAutowired();
            });

            return host;
        }
    }
}
